﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XTYAPI.PLC
{
    /// <summary>
    /// 两位五通电磁阀气缸控制
    /// </summary>
    public class QiGangControl
    {
        #region 字段
        /// <summary>
        /// 置位信号上升沿
        /// </summary>
        R_TRIG r_TRIG_Set = new R_TRIG();
        /// <summary>
        /// 置位信号下降沿
        /// </summary>
        F_TRIG f_TRIG_Rst = new F_TRIG();
        /// <summary>
        /// 气缸置位超时检测 默认8s
        /// </summary>
        #endregion

        #region 属性

        #region 输入
        /// <summary>
        /// 需要气缸置位
        /// </summary>
        public bool DI_Need_Set { get; set; }
        /// <summary>
        /// 是否检测气缸状态
        /// </summary>
        public bool DI_Enable_check { get; set; } = true;
        /// <summary>
        /// 气缸置位磁环感应检测
        /// </summary>
        public bool DI_Set_Check { get; set; }
        /// <summary>
        /// 气缸复位磁环感应检测
        /// </summary>
        public bool DI_Rst_Check { get; set; }
        /// <summary>
        /// 气缸置位磁环信号滤波 默认5ms
        /// </summary>
        public TON Ton_DI_Set_Check { get; private set; } = new TON(5);
        /// <summary>
        /// 气缸复位磁环信号滤波 默认5ms
        /// </summary>
        public TON Ton_DI_Rst_Check { get; private set; } = new TON(5);

        /// <summary>
        /// 气缸置位超时检测 默认8s
        /// </summary>
        public TON Ton_DI_Set_TimeOut { get; private set; } = new TON(8 * 1000);
        /// <summary>
        /// 气缸复位超时检测 默认8s
        /// </summary>
        public TON Ton_DI_Rst_TimeOut { get; private set; } = new TON(8 * 1000);
        #endregion

        #region 输出

        /// <summary>
        /// 气缸输出
        /// </summary>
        public bool DO_Set { get; private set; }
        /// <summary>
        /// 气缸执行错误
        /// </summary>
        public bool DO_Error { get {return DO_Err_Info.Length>0; } }
        /// <summary>
        /// 气缸错误信息
        /// </summary>
        public string DO_Err_Info { get; private set; }

        #endregion
       
        #endregion

        #region 枚举
        public enum State
        {
            RunLog,
            Begin,
            End,     
        }
        public enum InfoMode
        {
            Id,
            info,
            obj
        }
        #endregion

        #region 事件

        public event Action<State, InfoMode, object> Event_Alarm;

        #endregion

        #region 方法
        /// <summary>
        /// 执行气缸逻辑
        /// </summary>
        /// <returns></returns>
        public (bool, string) FunControl()
        {
            r_TRIG_Set.CLK = f_TRIG_Rst.CLK = DI_Need_Set;
            if (r_TRIG_Set.Q)//气缸置位处理
            {
                DO_Set = true;
            }
            if (f_TRIG_Rst.Q)//气缸复位处理
            {
                DO_Set = false;
            }
            #region 启用了磁环检测，并且气缸置位状态的处理
            Ton_DI_Set_Check.IN = DI_Set_Check;//置位磁环信号采集
            Ton_DI_Set_TimeOut.IN = DO_Set && Ton_DI_Set_Check.Q;
            if (Ton_DI_Set_TimeOut.Qp)//报警开始检测
            {                
                DO_Err_Info = "气缸置位超时，请检查气路、电路、或缸体老化";
                Event_Alarm?.Invoke(State.Begin,InfoMode.info, DO_Err_Info);
            }
            if (Ton_DI_Set_TimeOut.Qf)//报警消失检测
            {
                Event_Alarm?.Invoke(State.End, InfoMode.info, DO_Err_Info);
            }
            #endregion

            #region 启用了磁环检测，并且气缸复位状态的处理
            Ton_DI_Rst_Check.IN = DI_Rst_Check;//复位磁环信号采集
            Ton_DI_Rst_TimeOut.IN = !DO_Set && Ton_DI_Rst_Check.Q;
            if (Ton_DI_Rst_TimeOut.Qp)//报警开始检测
            {              
                DO_Err_Info = "气缸复位超时，请检查气路、电路、或缸体老化";
                Event_Alarm?.Invoke(State.Begin, InfoMode.info, DO_Err_Info);
            }
            if (Ton_DI_Rst_TimeOut.Qf)//报警消失检测
            {
                Event_Alarm?.Invoke(State.End, InfoMode.info, DO_Err_Info);
            }
            #endregion

            #region 没有开启磁环检测，自动复位相关内存或报警
            if (!DI_Enable_check)
            {
                RstAlarm();
            }
            #endregion

            return (true, "ok");
        }
        /// <summary>
        /// 复位报警
        /// </summary>
        public void RstAlarm()
        {
            Ton_DI_Set_TimeOut.IN = Ton_DI_Rst_TimeOut.IN = false;
            DO_Err_Info = string.Empty;
        }
        #endregion
    }
}
